package com.hsu.hsurpc.loadbalancer;

import com.hsu.hsurpc.model.ServiceMetaInfo;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 最少活跃数负载均衡器
 * @Author Hsu琛君珩
 * @Date 2024-09-24 16:39
 * @Description
 * @Version: v1.0.0
 */
public class LeastActiveLoadBalancer implements LoadBalancer {

    /**
     * 存储每个服务节点的活跃请求数
     * 使用 ConcurrentHashMap 保证在多线程环境下对活跃请求数的安全操作。
     */
    private final Map<ServiceMetaInfo, Integer> activeCountMap = new ConcurrentHashMap<>();

    /**
     * 从服务节点列表中选择一个活跃请求数最少的节点
     * 遍历所有服务节点，选择当前活跃数最少的节点进行请求分配，并增加该节点的活跃数。
     *
     * @param requestParams      请求参数，用于选择服务节点时的参考（此实现中未使用）
     * @param serviceMetaInfoList 服务节点的元数据信息列表，包含所有可用的服务节点
     * @return 返回活跃请求数最少的服务节点的元数据信息
     */
    @Override
    public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) {
        ServiceMetaInfo leastActiveNode = null;
        int leastActiveCount = Integer.MAX_VALUE;
        // 遍历服务节点，选择活跃数最少的节点
        for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfoList) {
            int activeCount = activeCountMap.getOrDefault(serviceMetaInfo, 0); // 获取节点的活跃请求数
            if (activeCount < leastActiveCount) {
                leastActiveNode = serviceMetaInfo; // 更新为当前活跃数最少的节点
                leastActiveCount = activeCount;
            }
        }
        // 增加选中节点的活跃数
        if (leastActiveNode != null) {
            activeCountMap.put(leastActiveNode, leastActiveCount + 1);
        }
        return leastActiveNode;
    }

    /**
     * 请求结束时调用，减少节点的活跃数
     * 当请求完成后调用此方法，将选中节点的活跃数减 1，确保统计准确性。
     *
     * @param serviceMetaInfo 完成请求的服务节点
     */
    public void onRequestComplete(ServiceMetaInfo serviceMetaInfo) {
        activeCountMap.computeIfPresent(serviceMetaInfo, (key, value) -> Math.max(0, value - 1));
    }
}
